const express = require("express");
const app = express();
const port = 3003;
// const cors = require("cors");
const user = require("./sql/user");
const yzbuser = require("./sql/yzbuser");
const moneylist1 = require("./sql/moneylist");
const path = require("path");
const fs = require("fs");
const http = require("http");

//跨域 谁都跨域访问我的服务器 即便vue和我不是一个域名和端口
//练习中使用很完美 因为我不是公网ip 也就只能我一个人访问
// app.use(cors());
const md5 = require("md5");
const bodyParser = require("body-parser");
app.use(bodyParser.json());
// 咱们前端用的很好用的一个 插件 它可以帮助你做 token算法的哪一步以及加入我们想要的随机值
//如果没有这个  token算法要我们自己写 随机值 要插入算法
const jwt = require("jsonwebtoken");
// 我要用bodypARSER  extended 扩展  false 就用这个
app.use(bodyParser.urlencoded({ extended: false }));
//中间件的其中一种写法 作为其他重大方法的拦截
//这个就是 中间件的一种写法  被express感染了 可以作为 单独一个函数 的中间件
const passwdcrpyt = function (req, res, next) {
  //123456
  let password = req.body.password;
  //为了解决密文泄露   全世界人都能下载查看  也只能看到加密的密码的密文
  //这样存进去就不单是一层md5的加密  双层再加 字符串截取
  var a = md5(password + md5(password).substr(10, 13));

  req.body.passwdcrpyt = a;
  next();
};
// login 登录逻辑
const jwt_secret = "aaa";
app.post("/api/v1/login", passwdcrpyt, async (req, res) => {
  console.log("/api/v1/login");
  //这一步呼应 上面中间件处理的哪一步 req.body.passwdcrpyt = a
  let { mobile, passwdcrpyt } = req.body;
  console.log("mobile", mobile);
  console.log("passwdcrpty", passwdcrpyt);
  let result = await user.findOne({ mobile, password: passwdcrpyt });
  if (result) {
    res.send({
      code: "1000",
      info: "success",
      mobile: mobile,
      data: {
        _token: jwt.sign(
          {
            // userId:result.userId,
            password: passwdcrpyt,
            mobile: result.mobile,
          },
          jwt_secret,
          { expiresIn: 60 * 600 }
        ),
      },
    });
  } else {
    res.send({
      code: "9999",
      info: "走开 你不是我的用户 ",
    });
  }
});

//写一个效验token的逻辑  中间件
const checkToken = function (req, res, next) {
  console.log("我进入校验token识别 这一步了");
  console.log("token");
  // 怎么样都可以传  这只是一种传递方式  能过来让服务器看见token就可以了
  console.log(req.headers.authorization);
  //因为req.headers.authorization 给你的不是原来的token 是加了bearer  dflksjdksfjlsfjsdfjsdf是这样的

  let temArr = req.headers.authorization.split(" ");
  let _token = temArr[1];
  console.log("_token");
  console.log(_token);

  //这里要做 更合理的  各种情况的处理
  try {
    // jwt引擎 反推这个秘文  是否是我给你的  是的话 把你秘文变成你的 用户信息 还原
    let verify = jwt.verify(_token, jwt_secret);
    console.log("verify");
    console.log(verify);
    if (verify) {
      console.log("我进入verify里面了");
      req.body.user_info = verify;
      console.log("req.body.user._info", req.body.user_info);
      next();
    }
  } catch (error) {
    res.send({
      code: "888",
      info: "你是不是没有我们的权限token乱来啊请重新登陆 ",
    });
  }
};

//这一步就是我们写 你已经登陆过app了  第二次 第三次 直接来token不用你费尽输入用户名密码 我通过token你也知道你是谁
//用户体验很爽   咱后端 也有办法知道识别你
app.get("/api/v1/user_info", checkToken, (req, res) => {
  console.log("进来了/api/v1/user_info");
  console.log(req.body.user_info);
  res.send({
    code: "1000",
    info: "success",
    info2: req.body.user_info,
  });
});

//注册逻辑
app.post("/api/zhuce", passwdcrpyt, (req, res) => {
  console.log("zhuce我进来了");
  var bbb = {
    mobile: req.body.mobile,
    // password:req.body.password,
    password: req.body.passwdcrpyt,
  };

  user.insertMany(bbb, (err, data) => {
    if (err) {
      console.log("err", err);
      res.send({
        code: "400",
        info: "fail",
        info2: "注册失败",
      });
    }
    console.log(data);
    res.send({
      code: "200",
      info: "success",
      info2: "注册成功",
    });
  });
});

// 初始化用户数据
app.post("/init", passwdcrpyt, (req, res) => {
  console.log("init");
  console.log(req.body);

  var bbb = {
    userId: 336633,
    mobile: "18888888888",
    password: req.body.passwdcrpyt,
    headIcon: "htttp/////////img",
    gender: 0,
  };
  user.insertMany(bbb, (err, data) => {
    if (err) {
      console.log("err", err);
    }
    console.log(data);
  });
  res.send("你的password 现在是  " + req.body.passwdcrpyt);
});

app.get("/", (req, res) => {
  res.send({
    name: "zs",
    token:
      "ddgsdfasfjiojfaiojfioajfiosjdfiosafjldfgjdlgjklfajgkljdkgladjkgjaskgfjaklfjklsajlksa",
  });
});

//pet 宠物大作战app   api
const pet = require("./sql/pet");
//加入买卖宠物信息  的后端接口
app.post("/addpet", (req, res) => {
  console.log("进来了addpet里面了");
  console.log(req.body.pet);
  //往数据库库插入 宠物 买卖信息
  pet.insertMany(req.body.pet, (err, data) => {
    if (err) {
      console.log(err);
    }
    console.log(data);
    res.send(data);
  });
});

//查询所有宠物信息  买卖的信息

app.post("/petall", (req, res) => {
  console.log("进来了petall里面了");
  console.log(req.body.pet);
  pet.find({}, (err, data) => {
    if (err) {
      console.log(err);
    }
    console.log(data);
    res.send(data);
  });
});

//宠物搜索   进入宠物搜索界面数据 后端请求
app.post("/search", (req, res) => {
  console.log("进来了search里面了");

  //   这里多了一步比对session key这一步
  //sessionkey是做网络安全的  能顶住很多共计
  //sessionkey能保证服务器  进来的请求 保证是我的用户 不是非法用户！！！！
  //req.body.sessionkey  === 后端sessionkey
  // res.send({
  //     msg:'你可能没有权限'
  // })

  console.log(req.body.dogtype);
  pet.find({ dogtype: req.body.dogtype }, (err, data) => {
    if (err) {
      console.log(err);
    }
    console.log(data);
    res.send(data);
  });
});

// axios 可以在后端使用

var axios = require("axios");
//  以下是微信鉴权API     集齐三颗龙珠的过程
app.post("/xcxauh", (req, res) => {
  console.log("进来xcauh里面了");
  console.log(req.body.code);
  //这是一颗龙珠
  var code = req.body.code;
  // const id = 'wxf43691de83ee1585'
  // appid  第二颗龙珠
  var id = "wx39b9b39b88c753b6";
  // const AppSecret = '05cdc310304bae33ce0f3a404039e668'

  //第三颗龙珠   到此为止三颗龙珠集齐
  var AppSecret = "2f81e4cd8c4a09c83db0b4d40e4db918";
  var url = `https://api.weixin.qq.com/sns/jscode2session?appid=${id}&secret=${AppSecret}&js_code=${req.body.code}&grant_type=authorization_code`;
  console.log(url);
  //此时的url 就是集齐龙珠后插槽插上的url
  axios.get(url).then((data) => {
    console.log("进入then里面了");
    console.log(data.data);
    //神龙的话传回来了
    res.send(data.data);
  });
});

// app.set('port',port)

// app.set('host','101.133.236.242')

//为小程序开发api

//react 在线账本项目 后端内容
app.post("/yunzhangbenlogin", async (req, res) => {
  console.log("进来/yunzhangbenlogin里面了");
  console.log(req.body);
  let { username, password } = req.body;
  console.log("username", username);
  console.log("password", password);
  let result = await yzbuser.findOne({
    username: username,
    password: password,
  });

  if (result) {
    res.send({
      code: "200",
      info: "success",
      info2: "登录成功",
      result: result,
    });
  } else {
    res.send({
      code: "400",
      info: "success",
      info2: "登录失败",
    });
  }
});

app.post("/yunzhangbenzhuce", (req, res) => {
  console.log("进来/yunzhangbenzhuce里面了");
  console.log(req.body);

  var bbb = {
    username: req.body.username,
    password: req.body.password,
  };
  yzbuser.findOne(bbb, (err, data) => {
    if (err) {
      console.log("err", err);
    }
    if (data) {
      res.send({
        code: "402",
        info: "fail",
        info2: "您是不是已经注册过了",
      });
    } else {
      yzbuser.insertMany(bbb, (err, data) => {
        if (err) {
          console.log("err", err);
          res.send({
            code: "400",
            info: "fail",
            info2: "注册失败",
          });
        }
        console.log(data);
        res.send({
          code: "200",
          info: "success",
          info2: "注册成功",
        });
      });
    }
  });
});

//后端存花费数据
app.post("/cunhuafeishuju", (req, res) => {
  console.log("进来//cunhuafeishuju里面了");
  console.log(req.body);

  var bbb = {
    username: req.body.username,
    title: req.body.title,
    price: req.body.price,
    date: req.body.date,
    category: [
      {
        incomeoutcome: req.body.incomeoutcome,
        type: req.body.type,
      },
    ],
  };
  console.log("bbb", bbb);

  moneylist1.insertMany(bbb, (err, data) => {
    if (err) {
      console.log("insertManyerr", err);
    } 
    if(data){
        res.send({
            shuju:data,
            code:200
        })
    }
  });
});




//get请求 money list数据
app.get("/moneylist", (req, res) => {
    console.log("进来/moneylist里面了");
    console.log(req.query);

    moneylist1.find({username:req.query.username},(err,data)=>{
        if(err) {
            console.log('err',err)
        }else{
            res.send({
                code:200,
                data
            })
        }
    })
   
  });

  // post请求 删除账本冗余内容 
  app.post('/deletemoney',(req,res)=>{
      console.log('进入//deletemoney 里面了')
      console.log(req.body)
      moneylist1.findByIdAndDelete(req.body.id,(err,data)=>{
          if(err){
              console.log('err',err)
          }
          res.send({
              code:200,
              data:data
          })
      })
  })






//  以下前后端连调代码  axios精讲

app.get("/axiosget1", (req, res) => {
  console.log("进来/axiosget1里面了");
  console.log(req.query);


  // res.status(401).send({
  //   code:'666',
  //   data:'我是数据666'
  // })

  setTimeout(()=>{
    res.status(401).send({
      // 4000代码代表这个用户 很危险 曾经多次尝试攻击我们服务器
      code:'4000',
      data:'可能存在什么错误哦'
    })
  },3000)

});




  // 轮询解决 后端要主动给前端  返回交互数据的需求  第一种解决方案
app.get('/lunxun',(req,res)=>{
  console.log('进入lunxun里面了')
  res.send({
    code:200,
    msg:'拼多多100元优惠券'
  })
})



// 第二种socket技术 实现服务器向客户端推送
// 第一步 先引入websocket的包
// const Websocket = require('ws')

// //  第二部  new出来一个超能力的 wss    给它传入一个参数{port:3000}
// var wss = new Websocket.Server({port:3000})


// wss.on('connection',ws=>{
//   //服务器监听消息事件  on  监听客户端给服务端
//   ws.on('message',msg=>{
//     console.log('服务器收到',msg)
//   })
// // send   服务端给客户端放
//   ws.send('卖车优惠广告')
// })


// scoket服务端设置
// 第一步引入 ws的包
const websocket = require('ws')
// 第二步 用 websocet功能 创建一个 websocket服务器 端口号是3500
var wss = new websocket.Server({port:3500})

// 设置服务器的监听  3500服务器
// connection 是监听链接成功状态 
wss.on('connection',ws=>{
  //  ws是监听成功状态后的 具体实例 
  console.log('后端websocket connection')
  ws.on('message',msg=>{
    // forEach 会把所有的 监听到的信息 发送给  共享代码的  前端电脑 
     wss.clients.forEach((computer)=>{
      computer.send(msg)
     })
  })
})








//react 在线账本项目 后端内容

app.listen(port, () => {
  console.log(
    "后端端口启动在" +
      port +
      "了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
  );
});
